package com.yuntian.controller;

import com.yuntian.dto.*;
import com.yuntian.service.CustomerService;
import com.yuntian.service.OrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

/**
 * 顾客主数据 M001 控制器
 * @author yuntian
 */
@Slf4j
@Controller
@RequiredArgsConstructor
public class CustomerController {

    private final CustomerService customerService;
    private final OrderService orderService;

    /**
     * 顾客主数据 M001 顾客列表
     * @return
     */
    @RequestMapping("/form")
    public String form(Model model){
        model.addAttribute("customers", customerService.getCustomerList());
        return "PR20201";
    }



    /**
     * PR20101 应收登记画面 初始显示
     * @param model
     * @return
     */
    @GetMapping("/PR20101")
    public String showPR20101(Model model) {
        initModel(model, false, false, false);
        return "PR20101";
    }

    /**
     * PR20101 应收登记画面 检索处理
     * @param orderId 受注代码
     * @param model
     * @return
     */
    @PostMapping("/getCustomer")
    public String postGetCustomer(@RequestParam("juchuu_code") String orderId, Model model){
        // 输入检查：必填、半角数字、5位
        String trimmed = orderId == null ? "" : orderId.trim();
        // 处理重复同名参数（hidden + text），仅取首个值
        if (trimmed.contains(",")) {
            String[] parts = trimmed.split(",");
            if (parts.length > 0) {
                trimmed = parts[0].trim();
            }
        }

        // 必填检查
        if (trimmed.isEmpty()) {
            model.addAttribute("errorMessage", "受注コードは必須です");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            log.info("受注コードが空です");
            return "PR20101";
        }

        // 格式检查
        if (!trimmed.matches("^[0-9]{5}$")) {
            model.addAttribute("errorMessage", "受注コードは半角数字5桁で入力してください");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            log.info("受注コードの形式が不正です: {}", trimmed);
            return "PR20101";
        }

        // 数据获取
        AccountReceivableDTO dto = orderService.findAccountReceivableByOrderCode(trimmed);
        if (dto == null) {
            model.addAttribute("errorMessage", "M201001E：対応する受注コードがありません。");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            log.info("受注コードに対応する受注データが存在しません: {}", trimmed);
            return "PR20101";
        }

        // 交货日期检查：已登记
        if (dto.getDeliveryDate() != null && !dto.getDeliveryDate().isEmpty()) {
            model.addAttribute("errorMessage", "M201002E：当該売掛はすでに登録されています。");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            log.info("受注コードに対応する受注データがすでに登録済みです: {}", trimmed);
            return "PR20101";
        }

        // 正常：展示结果并控制状态
        model.addAttribute("data", dto);
        model.addAttribute("orderCode", trimmed);
        initModel(model, true, true, true);
        log.info("受注コード {} の売掛情報を正常に取得しました", trimmed);
        return "PR20101";
    }

    /**
     * 通用的 Model 属性设置
     * @param model
     * @param registerEnabled 注册按钮启用/禁用
     * @param orderCodeDisabled 受注代码输入框启用/禁用
     * @param searchDisabled 搜索按钮启用/禁用
     */
    private void initModel(Model model, boolean registerEnabled,
                           boolean orderCodeDisabled, boolean searchDisabled) {
        model.addAttribute("registerEnabled", registerEnabled);
        model.addAttribute("orderCodeDisabled", orderCodeDisabled);
        model.addAttribute("searchDisabled", searchDisabled);
        log.info("共通のModel属性設定: registerEnabled={}, orderCodeDisabled={}, searchDisabled={}",
                registerEnabled, orderCodeDisabled, searchDisabled);
    }

    /**
     * 跳转到PR20201
     * @return
     */
    @RequestMapping("/PR20201")
    public String PR20201(Model model){
        java.util.List<String> customers = orderService.getCustomersNeedingInvoice();
        model.addAttribute("customers", customers);
        if (customers == null || customers.isEmpty()) {
            model.addAttribute("errorMessage", "M202001E：請求書を作成する必要の顧客がありません。");
        }
        model.addAttribute("selectedCustomerCode", "");
        return "PR20201";
    }

    @PostMapping("/registerAccountReceivable")
    public String registerAccountReceivable(
            @RequestParam("juchuu_code") String orderId,
            @RequestParam(value = "kotosi", required = false) String kotosi, // 交货年（平成纪年）
            @RequestParam(value = "gathu", required = false) String gathu, // 交货月
            @RequestParam(value = "niti", required = false) String niti, // 交货日
            Model model) {
        // 受注代码检查（必填、半角数字5位）
        String trimmed = orderId == null ? "" : orderId.trim();
        if (trimmed.isEmpty()) {
            model.addAttribute("errorMessage", "受注コードは必須です");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            return "PR20101";
        }
        if (!trimmed.matches("^[0-9]{5}$")) {
            model.addAttribute("errorMessage", "受注コードは半角数字5桁で入力してください");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            return "PR20101";
        }

        // 获取现有数据（防止重复登记）
        AccountReceivableDTO dto = orderService.findAccountReceivableByOrderCode(trimmed);
        if (dto == null) {
            model.addAttribute("errorMessage", "M201001E：対応する受注コードがありません。");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            return "PR20101";
        }
        if (dto.getDeliveryDate() != null && dto.getDeliveryDate().isEmpty()) {
            model.addAttribute("errorMessage", "M201002E：当該売掛はすでに登録されています。");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            return "PR20101";
        }

        // 解析交货日期；省略时默认今天
        LocalDate now = LocalDate.now();
        LocalDate deliveryLocalDate;
        boolean omitted = (kotosi == null || kotosi.isEmpty() || "0".equals(kotosi))
                || (gathu == null || gathu.isEmpty() || "0".equals(gathu))
                || (niti == null || niti.isEmpty() || "0".equals(niti));
        if (omitted) {
            deliveryLocalDate = now;
        } else {
            try {
                int heisei = Integer.parseInt(kotosi); // 例：19
                int year = 1988 + heisei; // 平成1年=1989
                int month = Integer.parseInt(gathu);
                int day = Integer.parseInt(niti);
                deliveryLocalDate = LocalDate.of(year, month, day);
            } catch (Exception e) {
                model.addAttribute("errorMessage", "M201003E：受注納入日付が不正です。");
                model.addAttribute("orderCode", trimmed);
                // 保持搜索后的页面状态
                initModel(model, true, true, true);
                return "PR20101";
            }
        }

        // 范围检查：去年同日至今天
        LocalDate lower = now.minusYears(1);
        if (deliveryLocalDate.isAfter(now) || deliveryLocalDate.isBefore(lower)) {
            model.addAttribute("errorMessage", "M201003E：受注納入日付が不正です。");
            model.addAttribute("orderCode", trimmed);
            initModel(model, true, true, true);
            return "PR20101";
        }

        try {
            // 登记处理（更新应收余额＋更新交货日期）
            AccountReceivableDTO result = orderService.registerAccountReceivable(trimmed, deliveryLocalDate);
            model.addAttribute("data", result);
            model.addAttribute("orderCode", trimmed);
            model.addAttribute("successMessage", "M201004I：売掛登録成功。");
            // 登记后恢复初始状态以便再次搜索
            initModel(model, false, false, false);
            return "PR20101";
        } catch (Exception e) {
            log.error("登録処理で例外が発生しました", e);
            model.addAttribute("errorMessage", "M00001E：ＳＱＬ実行例外が発生しました。");
            model.addAttribute("orderCode", trimmed);
            initModel(model, false, false, false);
            return "PR20101";
        }
    }

    @PostMapping("/createInvoice")
    public String createInvoice(
            @RequestParam("kokyaku_code") String customerCode,
            @RequestParam(value = "nengou_code", required = false) String nengouCode,
            @RequestParam(value = "kotosi", required = false) String kotosi,
            @RequestParam(value = "gathu", required = false) String gathu,
            @RequestParam(value = "niti", required = false) String niti,
            Model model
    ) {
        // 顾客代码为必填
        String cust = customerCode == null ? "" : customerCode.trim();
        if (cust.isEmpty()) {
            model.addAttribute("errorMessage", "顧客コードは必須です");
            model.addAttribute("selectedCustomerCode", cust);
            model.addAttribute("customers", orderService.getCustomersNeedingInvoice());
            return "PR20201";
        }

        // 请求日付：省略为今天，指定时将平成转换为公历
        LocalDate now = LocalDate.now();
        LocalDate reqDate;
        boolean omitted = (kotosi == null || kotosi.isEmpty() || "0".equals(kotosi))
                || (gathu == null || gathu.isEmpty() || "0".equals(gathu))
                || (niti == null || niti.isEmpty() || "0".equals(niti));
        if (omitted) {
            reqDate = now;
        } else {
            try {
                int heisei = Integer.parseInt(kotosi);
                int year = 1988 + heisei; // 平成1年=1989
                int month = Integer.parseInt(gathu);
                int day = Integer.parseInt(niti);
                reqDate = java.time.LocalDate.of(year, month, day);
            } catch (Exception e) {
                model.addAttribute("errorMessage", "M202002E：請求日付が不正です。");
                model.addAttribute("selectedCustomerCode", cust);
                model.addAttribute("customers", orderService.getCustomersNeedingInvoice());
                return "PR20201";
            }
        }
        LocalDate lower = now.minusYears(1);
        if (reqDate.isAfter(now) || reqDate.isBefore(lower)) {
            model.addAttribute("errorMessage", "M202002E：請求日付が不正です。");
            model.addAttribute("selectedCustomerCode", cust);
            model.addAttribute("customers", orderService.getCustomersNeedingInvoice());
            return "PR20201";
        }

        try {
            InvoiceCreationResult res = orderService.createInvoice(cust, reqDate);
            // 成功后跳转到静态页面 PR20202.htm（传递請求番号）
            return "redirect:/HTML/PR20202.htm?invoiceNo=" + res.getInvoiceNo();
        } catch (IllegalStateException ise) {
            model.addAttribute("errorMessage", ise.getMessage());
            model.addAttribute("selectedCustomerCode", cust);
            model.addAttribute("customers", orderService.getCustomersNeedingInvoice());
            return "PR20201";
        } catch (Exception e) {
            lombok.extern.slf4j.Slf4j.class.getName();
            model.addAttribute("errorMessage", "M00001E：ＳＱＬ実行例外が発生しました。");
            model.addAttribute("selectedCustomerCode", cust);
            model.addAttribute("customers", orderService.getCustomersNeedingInvoice());
            return "PR20201";
        }
    }

    @GetMapping("/HTML/PR20202.htm")
    public String showPR20202Htm(@RequestParam("invoiceNo") String invoiceNo, Model model) {
        InvoiceHeaderDTO header = orderService.getInvoiceHeader(invoiceNo);
        List<InvoiceDetailDTO> details = orderService.getInvoiceDetails(invoiceNo);
        long totalExcl = 0L, totalTax = 0L, totalIncl = 0L;
        for (InvoiceDetailDTO d : details) {
            totalExcl += d.getAmountExclTax() == null ? 0L : d.getAmountExclTax();
            totalTax += d.getTax() == null ? 0L : d.getTax();
            totalIncl += d.getAmountInclTax() == null ? 0L : d.getAmountInclTax();
        }
        model.addAttribute("header", header);
        model.addAttribute("details", details);
        model.addAttribute("totalExcl", totalExcl);
        model.addAttribute("totalTax", totalTax);
        model.addAttribute("totalIncl", totalIncl);
        // 复用 Thymeleaf 模板 PR20202.html
        return "PR20202_htm";
    }

    // ===== PR20301 入金登録 画面初期表示 =====
    @GetMapping("/PR20301")
    public String showPR20301(Model model) {
        List<String> customers = orderService.getCustomersNeedingPayment();
        model.addAttribute("customers", customers);
        if (customers == null || customers.isEmpty()) {
            model.addAttribute("errorMessage", "M203001E：必要な入金する顧客コードがありません。");
        }
        model.addAttribute("selectedCustomerCode", "");
        model.addAttribute("customerName", "");
        model.addAttribute("balance", null);
        model.addAttribute("afterBalance", null);
        model.addAttribute("invoices", java.util.Collections.emptyList());
        return "PR20301";
    }

    // ===== PR20301 入金登録 検索処理 =====
    @PostMapping("/PR20301/search")
    public String searchPR20301(@RequestParam("kokyaku_code") String customerCode, Model model) {
        String cust = customerCode == null ? "" : customerCode.trim();
        List<String> customers = orderService.getCustomersNeedingPayment();
        model.addAttribute("customers", customers);
        model.addAttribute("selectedCustomerCode", cust);
        if (cust.isEmpty()) {
            model.addAttribute("errorMessage", "顧客コードは必須です");
            return "PR20301";
        }
        PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
        List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
        model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
        model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
        model.addAttribute("invoices", invoices);
        return "PR20301";
    }

    // ===== PR20301 入金登録 登録処理 =====
    @PostMapping("/PR20301/register")
    public String registerPR20301(
            @RequestParam("kokyaku_code") String customerCode,
            @RequestParam(value = "selectedInvoiceNos", required = false) java.util.List<String> invoiceNos,
            @RequestParam(value = "nengou_code", required = false) String nengouCode,
            @RequestParam(value = "kotosi", required = false) String kotosi,
            @RequestParam(value = "gathu", required = false) String gathu,
            @RequestParam(value = "niti", required = false) String niti,
            Model model) {
        String cust = customerCode == null ? "" : customerCode.trim();
        List<String> customers = orderService.getCustomersNeedingPayment();
        model.addAttribute("customers", customers);
        model.addAttribute("selectedCustomerCode", cust);
        if (cust.isEmpty()) {
            model.addAttribute("errorMessage", "顧客コードは必須です");
            return "PR20301";
        }
        if (invoiceNos == null || invoiceNos.isEmpty()) {
            model.addAttribute("errorMessage", "M203002E：入金明細に少なくとも一つレコードを選択してください。");
            // 重新回填明细与顾客信息
            PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
            List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
            model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
            model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
            model.addAttribute("invoices", invoices);
            return "PR20301";
        }
        LocalDate now = LocalDate.now();
        LocalDate payDate;
        boolean omitted = (kotosi == null || kotosi.isEmpty() || "0".equals(kotosi))
                || (gathu == null || gathu.isEmpty() || "0".equals(gathu))
                || (niti == null || niti.isEmpty() || "0".equals(niti));
        if (omitted) {
            payDate = now;
        } else {
            try {
                int heisei = Integer.parseInt(kotosi);
                int year = 1988 + heisei; // 平成1年=1989
                int month = Integer.parseInt(gathu);
                int day = Integer.parseInt(niti);
                payDate = java.time.LocalDate.of(year, month, day);
            } catch (Exception e) {
                model.addAttribute("errorMessage", "入金日付が不正です。");
                PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
                List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
                model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
                model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
                model.addAttribute("invoices", invoices);
                return "PR20301";
            }
        }
        LocalDate lower = now.minusYears(1);
        if (payDate.isAfter(now) || payDate.isBefore(lower)) {
            model.addAttribute("errorMessage", "入金日付が不正です。");
            PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
            List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
            model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
            model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
            model.addAttribute("invoices", invoices);
            return "PR20301";
        }
        try {
            PaymentResult res = orderService.registerPayment(cust, payDate, invoiceNos);
            model.addAttribute("successMessage", "M203004I：入金登録成功。");
            model.addAttribute("afterBalance", res.getBalanceAfterRegistration());
            // 更新后重新加载顾客信息与剩余未入金請求
            PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
            List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
            model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
            model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
            model.addAttribute("invoices", invoices);
            return "PR20301";
        } catch (IllegalStateException e) {
            // 入金額が売掛残高を超過するなどの検証エラー
            log.warn("入金登録の検証エラー: {}", e.getMessage());
            model.addAttribute("errorMessage", e.getMessage());
            PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
            List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
            model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
            model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
            model.addAttribute("invoices", invoices);
            return "PR20301";
        } catch (Exception e) {
            log.error("入金登録処理で例外が発生しました", e);
            model.addAttribute("errorMessage", "M00001E：ＳＱＬ実行例外が発生しました。");
            PaymentCustomerDTO summary = orderService.getPaymentCustomerSummary(cust);
            List<PaymentInvoiceDTO> invoices = orderService.getUnpaidInvoices(cust);
            model.addAttribute("customerName", summary != null ? summary.getCustomerName() : "");
            model.addAttribute("balance", summary != null ? summary.getAccountReceivableBalance() : null);
            model.addAttribute("invoices", invoices);
            return "PR20301";
        }
    }
}
